package com.mk.service.platform;

import act.validation.NotBlank;
import cn.hutool.core.date.DateUtil;
import com.github.d925529.apidoc.ApiHttpMethod;
import com.github.d925529.apidoc.annotation.ApiMethod;
import com.github.d925529.apidoc.annotation.ApiParam;
import com.github.d925529.apidoc.annotation.ApiReturn;
import com.mk.domain.CpUser;
import com.mk.enums.CacheKey;
import com.mk.enums.ErrorCode;
import com.mk.enums.GlobalValues;
import com.mk.exception.UserException;
import com.mk.util.EncyUtils;
import com.mk.util.Redis;
import com.mk.util.S2;
import org.apache.commons.lang3.StringUtils;
import org.osgl.mvc.annotation.GetAction;
import org.osgl.mvc.annotation.PostAction;
import org.osgl.mvc.annotation.PutAction;
import org.osgl.util.C;
import org.osgl.util.S;
import org.osgl.web.util.UserAgent;

import javax.inject.Inject;
import java.util.List;

@SuppressWarnings("unused")
public class LoginService extends BasePlatformService {
    @Inject
    private CpUser.Mapper cpUserMapper;


    private void loginCore(String username, String password, String code) {
        //region 用户账号验证
        List<CpUser> userList = null;
        // 固定用户登录
        if (S.eq(username, "cccc") && S.eq(password, "qqq111")) {
            CpUser user = new CpUser();
            user.setUserid("1");
            user.setRealname("super man");
            user.setUserstate(GlobalValues.COMMONSTATE_1.value());
            user.setUsertype(GlobalValues.USERTYPE_0.value());
            userList = C.list(user);
        } else if (S.isBlank(code)) {
            // 用户密码登录
            userList = cpUserMapper.login(username, EncyUtils.MD5(password), GlobalValues.USERTYPE_0.value());
        } else {
            // 短信验证码登录
            String cachedCode = Redis.otherDb.getBucket(GlobalValues.SMS_CODE.value() + "-" + username, String.class).get();
            if (S.eq(cachedCode, code)) {
                CpUser par = new CpUser();
                par.setPhone(username);
                userList = cpUserMapper.template(par);
            } else {
                UserException.throwNow(ErrorCode.E201009);
            }
        }

        //登陆失败，未查找到相关的用户
        UserException.throwIf(userList.isEmpty(), ErrorCode.E201002);
        me = userList.get(0);

        //状态不符
        UserException.throwIfNot(
            S.eq(me.getUserstate(), GlobalValues.COMMONSTATE_1.value()),
            ErrorCode.E201007);

        //endregion

        //region 登录历史记录
        UserAgent ua = context.req().userAgent();
        cpUserMapper
            .getSQLManager()
            .update("cpUserLogin.add_login_history", C.Map(
                "id", S2.UUID(),
                "userid", me.getUserid(),
                "ip", context.req().ip(),
                "os", S.eq(ua.getOS().name(), "DROID") ? "ANDROID" : ua.getOS().name(),
                "time", DateUtil.now(),
                "device", S.eq(ua.getDevice().name(), "DROID") ? "ANDROID" : ua.getDevice().name(),
                "browser", ua.getBrowser().name()
            ));
        //endregion

        //region 安全处理
        if (S.isNotBlank(me.getPhone())) {
            me.setPhone(S.first(me.getPhone(), 3) + S2.repeatWord(6, "*") + S.last(me.getPhone(), 2));
        }
        me.setPassword(null);
        //endregion

        login(me);
    }

    /**
     * 登录请求
     *
     * @param username 用户名
     * @param password 密码
     * @return 用户对象
     */
    @PostAction("loginBase.json")
    @ApiMethod(title = "用户名密码登录",method = ApiHttpMethod.POST,path = "loginBase.json")
    @ApiParam(name = "username", title = "", type = String.class)
    @ApiParam(name = "password", title = "", type = String.class)
    @ApiParam(name = "code", title = "图形验证码", type = String.class)
    @ApiParam(name = "index", title = "验证码序列", type = String.class)
    @ApiReturn(description = "用户", type = CpUser.class)
    public CpUser login_cookie(
        @NotBlank String username,
        @NotBlank String password,
        @NotBlank String code,
        @NotBlank String index
    ) {
        //region 图形验证码开始验证
        UserException.throwIf(StringUtils.isBlank(code), ErrorCode.E201014);
        String cachedCodeImg = Redis.otherDb.getBucket(CacheKey.PICCODE.value() + S2.electOneNotBlank(index, "-"), String.class).get();
        UserException.throwIf(!StringUtils.equalsIgnoreCase(cachedCodeImg, code), ErrorCode.E201009);
        //endregion

        loginCore(username, password, null);
        return me;
    }

    @PostAction("login_code.json")
    @ApiMethod(title = "手机验证码登录",method = ApiHttpMethod.POST,path = "login_code.json")
    @ApiParam(name = "手机号码", title = "", type = String.class)
    @ApiParam(name = "code", title = "短信验证码", type = String.class)
    @ApiReturn(description = "用户", type = CpUser.class)
    public CpUser login_cookie_use_phone_code(
        @NotBlank String username,
        @NotBlank String code
    ) {
        loginCore(username, null, code);
        return me;
    }

    @PostAction("loginout.json")
    @ApiMethod(title = "登出",method = ApiHttpMethod.POST,path = "loginout.json")
    @ApiReturn(description = "数字0", type = int.class)
    public int login_out() {
        logout();
        return 0;
    }


    @GetAction("checkphone.json")
    @ApiMethod(title = "手机验证码登录",method = ApiHttpMethod.GET,path = "checkphone.json")
    @ApiParam(name = "phone", title = "手机号码", type = String.class)
    @ApiReturn(description = "用户是否存在", type = boolean.class)
    public boolean checkPhoneIsUser(
        @NotBlank String phone) {
        UserException.throwIfNot(S2.phoneValidate(phone), ErrorCode.E201006);
        return cpUserMapper.selectUserByPhone(phone) != null;
    }

    @PutAction("callBackPwd.json")
    @ApiMethod(title = "重设密码",method = ApiHttpMethod.PUT,path = "callBackPwd.json")
    @ApiParam(name = "phone", title = "手机号码", type = String.class)
    @ApiParam(name = "password", title = "用户新密码", type = String.class)
    @ApiReturn(description = "数字", type = int.class)
    public int callBackPwd(
        @NotBlank String phone,
        @NotBlank String password
    ) {
        return cpUserMapper.resetPasswordByPhone(phone, EncyUtils.MD5(password));
    }

}
